/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 *
 */

import { coreParameter, FileSet, getWorkerIdWithModule, PoolConstant, setWorkerIdWithModule } from '@ohos/hvigor';
import { ProjectConfig } from '@ohos/hvigor-arkts-compose';
import * as fse from 'fs-extra';

import { getJson5Obj } from '../utils/json-util.js';
import { OhosLogger } from '../utils/log/ohos-logger.js';
import { mod } from '../utils/math-util.js';

import { submitArkCompileWork } from './worker/run-ark.js';
import { ArkCompile } from './ark-compile.js';
import { ArkPackConst } from '../const/common-const.js';

export class ColdReloadArkCompile extends ArkCompile {
  logger: OhosLogger = OhosLogger.getLogger(ColdReloadArkCompile.name);

  taskShouldDo(): boolean {
    const buildConfigPath = this.pathInfo.getBuildConfigPath();
    return super.taskShouldDo() && fse.existsSync(buildConfigPath);
  }

  declareInputFiles(): FileSet {
    const inputFiles = super.declareInputFiles();
    const buildConfigJsonPath = this.pathInfo.getBuildConfigPath();
    if (fse.existsSync(buildConfigJsonPath)) {
      const buildConfig = getJson5Obj(buildConfigJsonPath);
      const changedFileListPath = buildConfig?.patchConfig?.changedFileList;
      if (changedFileListPath && fse.existsSync(changedFileListPath)) {
        inputFiles.addEntry(changedFileListPath);
      }
    }
    return inputFiles;
  }

  protected async doTaskAction(): Promise<void> {
    const buildConfigPath: string = this.pathInfo.getBuildConfigPath();
    let compileConfig;
    let patchConfig;
    if (fse.existsSync(buildConfigPath)) {
      const buildConfig = getJson5Obj(buildConfigPath);
      compileConfig = buildConfig.compileConfig;
      patchConfig = buildConfig.patchConfig;
    } else {
      this.logger.debug(`Build config file not found: ${buildConfigPath}`);
    }
    const config: ProjectConfig = {
      ...(await this.initDefaultArkCompileConfig()),
      ...(compileConfig ?? {}),
    };
    if (config.obfuscationOptions) {
      delete config.obfuscationOptions;
    }
    config.aceModuleJsonPath = this.pathInfo.getIntermediatesArkModuleJsonPath();

    // 屏蔽热重载
    config.watchMode = 'false';
    config.projectPath = config.aceModuleRoot;
    if (config.collectImportersConfig) {
      config.collectImportersConfig.isReload = true;
    }
    fse.ensureDirSync(config.cachePath!);
    fse.ensureDirSync(config.aceModuleBuild!);
    this._log.debug(`coldReload build config: ${config}`);
    if (patchConfig && config.aceBuildJson && fse.existsSync(config.aceBuildJson)) {
      const loaderConfig = getJson5Obj(config.aceBuildJson);
      loaderConfig.patchConfig = patchConfig;
      fse.outputJSONSync(config.aceBuildJson, loaderConfig);
    }

    let ohosArkCompileMaxSize = coreParameter.properties.ohosArkCompileMaxSize;
    if (ohosArkCompileMaxSize === undefined || ohosArkCompileMaxSize <= 0 || ohosArkCompileMaxSize > PoolConstant.MAX_POOL_NUM) {
      ohosArkCompileMaxSize = ArkPackConst.MAX_ARK_COMPILE_NUM;
    }
    const maxPoolNum = this.getWorkerPool().getMaxPoolNum();
    let targetWorkers = [...new Array(ohosArkCompileMaxSize).keys()];
    const moduleWorkerId: number | undefined = getWorkerIdWithModule(config.modulePath);
    if (moduleWorkerId !== undefined && maxPoolNum > 0) {
      targetWorkers = [mod(moduleWorkerId!, Math.min(maxPoolNum, ohosArkCompileMaxSize))];
    }
    let workId: string | null = null;
    workId = await submitArkCompileWork(
      this,
      this.getWorkerPool(),
      this.logger,
      config,
      (compileEvents: object[], workerId?: number) => {
        if (workerId !== undefined) {
          setWorkerIdWithModule(config.modulePath, workerId);
        }
        !!workId && this.handleCompileEvents(compileEvents, this.getSubDurationEvent(workId), true);
      },
      targetWorkers,
    );
  }

  initTaskDepends(): void {
    this.dependsOnHook('buildHotReloadResource');
  }
}
